/*
 * 文件名：AspectConfig.java
 * 版权：Copyright by www.nd.com
 * 描述：
 * 修改人：Administrator
 * 修改时间：2016年10月24日
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package com.wmzdq.config;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.wmzdq.common.IControllerLogService;
import com.wmzdq.dto.Controllerlog;
import com.wmzdq.framework.util.DateUtil;
import com.wmzdq.security.UserDetailsImpl;

//定义一个切面
@Component
@Aspect
public class AspectConfig
{

    private static final Logger logger = LoggerFactory.getLogger(AspectConfig.class);
    
	@Autowired
	IControllerLogService controllerService; 
	
	@Value("${saveController}")
	String flag;
    /*//检验切面事务是否正常
    @Pointcut("execution(* com.wmzdq.test.common.TestUserService.testAdvice(..))")
    public void init(){
        
    }
    
    //测试切面事务 和@Transactional 同时配置的时候,哪个起作用
    //结论@Transactional 起作用
    @Pointcut("execution(* com.wmzdq.test.common.TestUserService.testTransactional(..))")
    public void allInit(){
        
    }*/
    
    //通用 事务配置
    @Pointcut("execution(* com.wmzdq.common..*.*(..))")
    public void base(){
        
    }
    
    //@Before()
    
    //controll层访问参数入库
    @Pointcut("execution(* com.wmzdq.framework.controller.BaseController+.*(..))")
    public void insertController(){

    }
    
  /*  @Pointcut("@annotation(com.wmzdq.framework.annotation.SystemControllerLog)")    
    public  void controllerAspect() {    
    }    */
    
    @Before("insertController()")
    public void doControllerBefore(JoinPoint joinPoint){
      //  String flag=ent.getProperty("saveController");
        if("1".equals(flag)){
            HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
            //请求类型
            String clazName=joinPoint.getTarget().getClass().getName() ;
            //请求方法
            String methodName= joinPoint.getSignature().getName() ;
            //HttpSession session = request.getSession();    
            //读取登录用户    
            Object user;
            Authentication authentication = SecurityContextHolder.getContext()
    				.getAuthentication();
    		if (authentication == null) {
    			user= null;
    		}
    		else{
        		user = authentication.getPrincipal();
    		}
            //请求的IP    
            String ip = request.getRemoteAddr();    
            //请求参数名
            try{
                String[] paramNames=getParamNames( joinPoint,clazName, methodName);
                //请求参数
                String params = ""; 
                Map<String, String> paramMap=new HashMap<String, String>();
                if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    
                    for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
                       //params += JSON.toJsonString(joinPoint.getArgs()[i]) + ";";  
                    	if(i<paramNames.length){
                    		paramMap.put(paramNames[i], joinPoint.getArgs()[i].toString());
                    	}
                   }    
               }
                params=JSON.toJSONString(paramMap);
                 try {    
                    //*========控制台输出=========*//    
                    //System.out.println("=====前置通知开始=====");    
                   // System.out.println("请求方法:" +clazName+"."+methodName+"()" );    
                    //System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));
                   /* if(user!=null)
                   	System.out.println("请求人:" + user.getUsername());    */
                   // System.out.println("请求IP:" + ip);    
                    //*========数据库日志=========*//    
                    Controllerlog log=new  Controllerlog();
                   log.setControllername(clazName);
                   log.setCreatetime(DateUtil.currentDateLong());
                   log.setMethod(methodName);
                   log.setParam(params);
                   if(user!=null){
                	   log.setUserinof(JSON.toJSONString(user));
                	   if(user instanceof UserDetailsImpl)
                		   log.setUserid(((UserDetailsImpl)user).getUserEntity().getId());
                   }
                   
                    //保存数据库    
                    controllerService.save(log);;    
                    System.out.println("=====前置通知结束=====");    
                }  catch (Exception e) {    
                    //记录本地异常日志    
                    logger.error("==前置通知异常==");    
                    logger.error("异常信息:{}", e.getMessage());    
                	e.printStackTrace();
                }    
            }catch (Exception e) {
                // TODO: handle exception
                logger.error("无法获取参数名称，请确认是否是jdk1.8");
                logger.error("doControllerBefore 保存失败");
                e.printStackTrace();
            }
        }
       // System.out.println("拦截到了");
    }
    
    /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    //description = method.getAnnotation(SystemControllerLog. class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    
     
     //获取参数名，适用于1.8
     public static String[] getParamNames(JoinPoint joinPoint,String clazName,String methodName) throws ClassNotFoundException{
    	 /*String[] paramNames=new String[0];
    	 Class targetClass=Class.forName(clazName);
    	 for(Method method:targetClass.getMethods()){
    		 if(method.getName().equals(methodName)){
    			 paramNames=new String[method.getParameterCount()];
    			 int i=0;
    			 for (Parameter p : method.getParameters()) {
    	                //System.out.println("parameter: " + p.getType().getName() + ", " + p.getName());
    				 paramNames[i]=p.getName();
    	            }
    		 }
    	 }
    	 return paramNames;*/
    	 Signature signature = joinPoint.getSignature();
    	 MethodSignature methodSignature = (MethodSignature) signature;
    	 String[] paramNames= methodSignature.getParameterNames();
    	 return paramNames;
     }

}
